#include "push_pdo.h"

extern void push_db_data(string addr, string query, string error, long execute_micro_time);

void push_pdo_handler(zend_execute_data *execute_data, zval *return_value, long execute_micro_time, string class_name, string function_name)
{
    // 初始化参数
    string host = "127.0.0.1";
    string port = "3306";
    string addr = "";
    string sql = "";
    string err = "";
    string query = "";

    // 获取数据库连接地址
    zval obj = execute_data->This;
    pdo_dbh_t *dbh = Z_PDO_DBH_P(&obj);
    string dsn = dbh->data_source;
    // vector<string> dsn_attrs = split(dsn, ';');
    vector<string> dsn_attrs = split(dsn, ";");
    for (auto attr : dsn_attrs)
    {
        // vector<string> kv = split(attr, '=');
        vector<string> kv = split(attr, "=");
        if (kv[0] == "host")
        {
            host = kv[1];
        }
        if (kv[0] == "port")
        {
            port = kv[1];
        }
    }

    addr = host + ":" + port;

    // 获取函数传参
    uint32_t arg_count = ZEND_CALL_NUM_ARGS(execute_data);
    if (arg_count)
    {
        zval *statement = ZEND_CALL_ARG(execute_data, 1);
        if (Z_TYPE_P(statement) == IS_STRING)
        {
            string sql_string = Z_STRVAL_P(statement);
            // vector<string> sql_str = split(sql_string, ' ');
            vector<string> sql_str = split(sql_string, " ");
            sql = sql_str[0];
        }
    }

    // 获取错误信息
    pdo_stmt_t *stmt = dbh->query_stmt;
    pdo_error_type *pdo_err = &dbh->error_code;
    zval error_value;
    array_init(&error_value);
    add_next_index_string(&error_value, *pdo_err);
    if (Z_TYPE_P(return_value) == IS_FALSE)
    {
        if (dbh->methods->fetch_err)
        {
            dbh->methods->fetch_err(dbh, stmt, &error_value);
            zval *value = zend_hash_index_find(Z_ARRVAL_P(&error_value), 2);
            if (value != NULL && Z_TYPE_P(value) == IS_STRING)
            {
                err = Z_STRVAL_P(value);
            }
        }
    }
    else
    {
        err = "";
    }

    query = class_name + "->" + function_name + "::" + sql;

    push_db_data(addr, query, err, execute_micro_time);
}

void push_pdo_stmt_handler(zend_execute_data *execute_data, zval *return_value, long execute_micro_time, string class_name, string function_name)
{
    // 初始化参数
    string host = "127.0.0.1";
    string port = "3306";
    string addr = "";
    string sql = "";
    string err = "";
    string query = "";
    
    zval obj = execute_data->This;
    pdo_stmt_t *stmt = Z_PDO_STMT_P(&obj);
    pdo_dbh_t *dbh = stmt->dbh;

    // 获取数据库连接地址
    string dsn = dbh->data_source;
    // vector<string> dsn_attrs = split(dsn, ';');
    vector<string> dsn_attrs = split(dsn, ";");
    for (auto attr : dsn_attrs)
    {
        // vector<string> kv = split(attr, '=');
        vector<string> kv = split(attr, "=");
        if (kv[0] == "host")
        {
            host = kv[1];
        }
        if (kv[0] == "port")
        {
            port = kv[1];
        }
    }

    addr = host + ":" + port;

    // 获取函数传参
    string sql_string = stmt->query_string;
    // vector<string> sql_str = split(sql_string, ' ');
    vector<string> sql_str = split(sql_string, " ");
    sql = sql_str[0];

    // 获取错误信息
    pdo_error_type *pdo_err = &stmt->error_code;
    zval error_value;
    array_init(&error_value);
    add_next_index_string(&error_value, *pdo_err);
    if (Z_TYPE_P(return_value) == IS_FALSE)
    {
        if (stmt->dbh->methods->fetch_err)
        {
            stmt->dbh->methods->fetch_err(dbh, stmt, &error_value);
            zval *value = zend_hash_index_find(Z_ARRVAL_P(&error_value), 2);
            if (value != NULL && Z_TYPE_P(value) == IS_STRING)
            {
                err = Z_STRVAL_P(value);
            }
        }
    }
    else
    {
        err = "";
    }

    query = string(class_name) + "->" + string(function_name) + "::" + sql;

    push_db_data(addr, query, err, execute_micro_time);
}